home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
PROLOG
/
HUMBOLT
/
HUMBOLTS
/
_files
/
_humboltsr
/
READ._c
< prev
next >
Wrap
Text File
|
1990-06-10
|
23KB
|
909 lines
/***************************************************
****************************************************
** **
** HU-Prolog Portable Interpreter System **
** **
** Release 1.62 January 1990 **
** **
** Authors: C.Horn, M.Dziadzka, M.Horn **
** **
** (C) 1989 Humboldt-University **
** Department of Mathematics **
** GDR 1086 Berlin, P.O.Box 1297 **
** **
****************************************************
***************************************************/
#include "systems.h"
#include "types.h"
#include "errors.h"
#include "atoms.h"
#include "files.h"
#include "maxvars.h"
/*
[6] READIN
ReadIn reads a Prolog sentence from the current input file and builds a
term from it. The sentence is parsed using a shift- reduce parsing
algorithm which depends on operator information in atom entries.
*/
IMPORT TERM A0,A1;
IMPORT char CH,LASTCH; /* from linebuffer.c */
IMPORT void ABORT(),ERROR(),SYSTEMERROR(),SYNERROR();
IMPORT int ERRPOS;
IMPORT boolean WARNFLAG;
IMPORT ATOM LOOKUP(),LOOKATOM();
IMPORT boolean In_Toplevel_Read;
IMPORT TERM LISTREP();
IMPORT boolean UNIFY();
IMPORT boolean unget,ECHOFLAG;
IMPORT int FirstCharPos;
IMPORT void fillbuffer();
LOCAL boolean FILEENDED(void)
{
if(!unget && CHARPOS >=LINELENGTH && !ISTTY(inputfile))
fillbuffer();
return (!unget && ISEOF(inputfile) && (CHARPOS >=LINELENGTH));
}
/* Get the next character of the current input file in 'ch'. */
/* inline-code in READIN */
LOCAL void GETCHAR(void)
{
if(unget){unget=false; return;}
LASTCH=CH;
if(FILEENDED()){CH= '\n'; return; }
if( CHARPOS >=LINELENGTH ){
/* no char's in the buffer */
fillbuffer();
}
CH=LINEBUF[CHARPOS++] ;if(ECHOFLAG)wc(CH);
if(CH== '\n') {FirstCharPos=CHARPOS ; ERRPOS=0; LINENUMBER++;}
}
LOCAL boolean LINEENDED(void)
{ if(CHARPOS >=LINELENGTH && !ISTTY(inputfile))
fillbuffer();
return (FILEENDED() || LINEBUF[CHARPOS]== '\n');
}
LOCAL void REGET(void)
{ unget=true;
}
#if !BIT8
#define STRINGSPACE 256 /* Size of string buffer. */
#endif
#if BIT8
#define STRINGSPACE 128 /* Size of string buffer. */
#endif
LOCAL char ATOMTAB[STRINGSPACE+1]; /* also used in help.c */
LOCAL int ATOMINDEX;
LOCAL void ATOMCHAR (register char C)
{ if(ATOMINDEX>=STRINGSPACE) ERROR(aSTRINGSPACEE);
ATOMTAB[ATOMINDEX++]=C;
}
/*
EXPORT TERM READIN();
EXPORT boolean DOREAD();
EXPORT TERM VARTERM();
EXPORT int VARCOUNT;
EXPORT PREC LPREC(),RPREC();
EXPORT CHARCLAS[];
*/
#if BIT32
#define READSIZE 2000 /* Size of stack */
#define READDEPTH 1000 /* Max. nesting depth */
#endif
#if BIT16
#define READSIZE 250
#define READDEPTH 250
#endif
#if BIT8
#define READSIZE 50
#define READDEPTH 50
#endif
#if BIT8
#define VARLIMIT 100
#endif
#if BIT16
#define VARLIMIT 200
#endif
#if BIT32
#define VARLIMIT 2000
#endif
#define RBRACE '}'
/* characters are classified as follows:
small letters a..z: SC
large letters A..Z_: BC
digits 0..9: DC
spaces C0
atomic characters OC
special characters ( ) ' " [ ] { } | ,
are coded by itself
and all other characters are coded as 0
*/
#define SC 1
#define BC 2
#define DC 3
#define OC 4
#define C0 5
char CHARCLASS[256]=
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
/*--------------------------------------------------------------------*/
/*0*/ { C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0,
/*1*/ C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0,
/*2*/ C0,'!','"', OC, SC, OC,OC,'\'','(',')', OC, OC,',', OC, OC, OC,
/*3*/ DC, DC, DC, DC, DC, DC, DC, DC, DC, DC, OC, OC, OC, OC, OC, OC,
/*4*/ OC, BC, BC, BC, BC, BC, BC, BC, BC, BC, BC, BC, BC, BC, BC, BC,
/*5*/ BC, BC, BC, BC, BC, BC, BC, BC, BC, BC, BC,'[', OC,']', OC, BC,
/*6*/ OC, SC, SC, SC, SC, SC, SC, SC, SC, SC, SC, SC, SC, SC, SC, SC,
/*7*/ SC, SC, SC, SC, SC, SC, SC, SC, SC, SC, SC,'{','|','}','~', C0 };
#define isdigit(CH) (CHARCLASS[CH]==DC )
/* The precedence for a left operand of a. */
GLOBAL PREC LPREC (ATOM A)
{ switch (oclass(A))
{ case XFO:
case XFXO:
case XFYO:
return oprec(A)-1;
default:
return oprec(A);
}
}
/* The precedence for a right operand of a. */
GLOBAL PREC RPREC (ATOM A)
{ switch (oclass(A))
{ case FXO:
case XFXO:
case YFXO:
return oprec(A)-1;
default:
return oprec(A);
}
}
/*
Input and parse a Prolog sentence and build a term from it. The
finite state part of the parser is characterized by the variables
'context' and 'expected'.
'context' indicates the construct being parsed:
outerK The outermost level of a sentence.
innerK An expression in parentheses.
funcK The arguments of a functor.
listK The elements of a list.
endlistK A list continuation (between '|' or ',..'
and ']' in a list).
curlyK An expression in curly brackets.
'expected' indicates whether the next symbol is to be an operator
(opX) or an operand (randX).
Two stacks are used: one, represented by the array 'stack', to hold
parts of incompletely parsed terms, the other, represented by the
array 'statestack', to hold contextual information during parsing of
nested constructs. In fact, the parsing algorithm corresponds to a
stack machine with a single stack, but two stacks are used only as a
matter of convenience.
*/
#define OUTERK 0
#define INNERK 1
#define FUNCK 2
#define LISTK 3
#define ENDLISTK 4
#define CURLYK 5
#define STATE int
#define TERML 0
#define OPL 1
#define FUNCL 2
#define MARKL 3
#define ELEMTAG int
LOCAL STATE CONTEXT;
LOCAL boolean OPEXPECTED;
LOCAL PREC HIPREC, LOPREC;
LOCAL int RTOP;
LOCAL TERM TSTACK[READSIZE];
LOCAL ATOM ASTACK[READSIZE];
LOCAL ELEMTAG TAGSTACK[READSIZE];
LOCAL void RPOP(register ATOM *PA, register TERM *PT)
{ *PA=ASTACK[RTOP]; *PT=TSTACK[RTOP]; RTOP--; }
LOCAL void RPUSH (register ELEMTAG T, register ATOM A, register TERM X)
{ if(RTOP>=READSIZE) SYNERROR(READSTACKE);
RTOP++;
TAGSTACK[RTOP]=T; ASTACK[RTOP]=A; TSTACK[RTOP]=X;
}
LOCAL int STOP;
LOCAL int READCONTEXT[READDEPTH],
READPREC[READDEPTH];
LOCAL void SAVECONTEXT(void)
{ if(STOP>=READDEPTH) SYNERROR(READNESTE);
READCONTEXT[STOP]=CONTEXT; READPREC[STOP]=HIPREC; STOP++;
}
LOCAL void RESTORECONTEXT(void)
{ STOP--; CONTEXT=READCONTEXT[STOP]; HIPREC=READPREC[STOP];
}
int VARCOUNT;
/*
LOCAL struct
{ string aIDENT;
TERM ROOTVAR;
int counter;} VARTABLE[MAXVARS];
*/
LOCAL string aIDENT[MAXVARS];
/*LOCAL*/ TERM VAR_TAB[MAXVARS]; /* also used in write.c */
LOCAL int counter[MAXVARS];
TERM VARTERM(void)
{ TERM Q,R; int I;
if(VARCOUNT==0) return nil_term;
R=nil_term;
for(I=VARCOUNT-1; 0<=I; I--)
{ Q=mk2sons(LOOKUP(aIDENT[I],0,false),nil_term,
VART,VAR_TAB[I]);
if(non_nil_term(R)) R=mkfunc(NL_2,mk2sons(ISEQ_2,Q,VART,R));
else R=mkfunc(ISEQ_2,Q);
}
if(non_nil_term(R))
{ Q=mk2sons(WRITE_1,R,GOTO_1,
mk2sons(NOT_1,mkfunc(ASK_1,mkint(59)),nil_atom,nil_term));
return Q;
}
return nil_term;
}
/*
Collapse items on the stack. Before each reduction step, the
operator a on top of the stack is "balanced" against the
precedences p=b@.oprec and lp=Lprec(b) of a new operator b,
to see if a could be a left operand of b, or b a right operand of
a. If neither is possible or both are possible, a precedence
conflict is reported. If only the first is possible, a reduction
step is taken. If only the second is possible, reduction is
complete.
*/
LOCAL void REDUCE (PREC P, PREC LP)
{ TERM X, Y;
ATOM A,XA,YA;
RPOP(&XA,&X);
while(TAGSTACK[RTOP]==OPL)
{ A=ASTACK[RTOP];
if(RPREC(A)>=P)
if(oprec(A)<=LP) SYNERROR(PRECE);
else break;
else
if(oprec(A)>LP) SYNERROR(PRECE);
else
{ RTOP--;
switch (oclass(A))
{ case FXO:
case FYO:
X=mkfunc(XA,X); XA=A;
break;
case XFXO:
case XFYO:
case YFXO:
RPOP(&YA,&Y); X=mk2sons(YA,Y,XA,X); XA=A; break;
case XFO:
case YFO:break;
case NONO: break;
default: SYSTEMERROR("REDUCE");
}
}
}
RPUSH(TERML,XA,X);
}
/*
Attempt to force the state required for a delimiter.
This state must satisfy the predicate
(expected=opX) and (context in s).
If initially (expected=randX) and the top item on the stack
is a prefix operator, this operator is converted to an atom.
This allows for constructions such as (?-) in which a prefix
operator occurs as an atom.
*/
LOCAL void CHECKDELIM (void)
{ ATOM A; TERM X;
if(!OPEXPECTED)
{ if(TAGSTACK[RTOP]!=OPL) SYNERROR(NEEDRANDE);
RPOP(&A,&X);
if(oclass(A)!=FXO && oclass(A)!=FYO) SYNERROR(NEEDRANDE);
RPUSH(TERML,LOOKATOM(A,0),nil_term);
}
REDUCE(MAXPREC,MAXPREC);
}
/* Process an atom. */
LOCAL void SQUASHRAND (ATOM A)
{ PREC P, LP;
P=oprec(A);
LP=LPREC(A);
if(LP<LOPREC ||
(P>SUBPREC &&
CONTEXT!=OUTERK && CONTEXT!=INNERK && CONTEXT!=CURLYK))
SYNERROR(PRECE);
REDUCE(P,LP);
}
/* Read an atom or string quoted by 'q' and store its characters
in the atom table, translating pairs of embedded quotes. */
LOCAL void SCANQUOTE (char Q)
{
ATOMINDEX=0;
for(;;)
{
if(CH==Q)
{ GETCHAR(); if(CH!=Q) return; }
if(CH=='\\')
{ int suM;
GETCHAR();
switch(CH)
{ case 'n': CH='\n'; break;
case 'r': CH='\r'; break;
case 'b': CH='\b'; break;
case 't': CH='\t'; break;
case 'f': CH='\f'; break;
case 'v': CH='\v'; break;
case 'a': CH='\007';break;
case '\\': CH= '\\';break;
default:
if(CHARCLASS[CH]!=DC)break;
sum=CH - '0';
GETCHAR();
if(CHARCLASS[CH] !=DC)
{
if(ATOMINDEX>=STRINGSPACE) ERROR(aSTRINGSPACEE);
ATOMTAB[ATOMINDEX++]=sum;
continue;
}
sum=sum * 8 + CH - '0';
GETCHAR();
if(CHARCLASS[CH] !=DC)
{
if(ATOMINDEX>=STRINGSPACE) ERROR(aSTRINGSPACEE);
ATOMTAB[ATOMINDEX++]=sum;
continue;
}
sum=sum * 8 + CH - '0';
CH= (char)(sum & 0377);break;
}
}
if(ATOMINDEX>=STRINGSPACE) ERROR(aSTRINGSPACEE);
ATOMTAB[ATOMINDEX++]=CH;
GETCHAR();
}
}
/* Enter a variable and return it as a term. */
/* variable handling */
LOCAL int VARHWM;
LOCAL TERM ENTERVAR (void)
{ TERM V;
int N=0,NEWINDEX;
static char vtab[VARLIMIT];
string NEWVAR;
NEWVAR= &vtab[VARHWM]; NEWINDEX=VARHWM;
vtab[NEWINDEX++]=LASTCH;
while(SC<=CHARCLASS[CH] && CHARCLASS[CH]<=DC)
{ if(NEWINDEX>=VARLIMIT) ABORT(VARSPACEE);
vtab[NEWINDEX++]=CH;
GETCHAR();
}
vtab[NEWINDEX++]=0;
while(N!=VARCOUNT)
{ N++;
if(strcmp(aIDENT[N-1],NEWVAR)==0){
counter[N-1]++;
return VAR_TAB[N-1];}
}
if(VARCOUNT>=MAXVARS) SYNERROR(NVARSE);
VARCOUNT++;
VARHWM=NEWINDEX;
V=mkfreevar();
aIDENT[VARCOUNT-1]=NEWVAR;
VAR_TAB[VARCOUNT-1]=V;
counter[VARCOUNT-1]=1;
return V;
}
LOCAL void Var_Check(void)
{ int i;
/* check if a variable is only used only at one time */
for(i=0;i<VARCOUNT;i++)
if(counter[i]==1)
{ ws("WARNING: "); ws(aIDENT[i]); ws(" used only once ! \n"); }
}
#if REALARITH
LOCAL REAL genreal(REAL r, int expo)
{while(expo >=10 ) {expo-=10; r *=1e10;}
while(expo >=1){ expo-- ; r *=10.0; }
while(expo <= -10 ){expo +=10; r *=1e-10;}
while(expo <= -1) { expo ++ ; r *=0.1;}
return r;
}
#endif
#if REALARITH && LONGARITH
LOCAL TERM readnumber(boolean sign)
{LONG l ; int i ; REAL r ;
boolean esign=false;
int expo=0;
l= (LONG)(i=LASTCH-'0');
r= (REAL)i;
while(isdigit(CH)){
l=l * 10l + (LONG)(CH -'0');
i=i * 10 + (CH -'0');
r=r * 10.0 + (REAL)(CH -'0');
GETCHAR();
}
GETCHAR();
if(LASTCH== '.' && isdigit(CH))goto double1;
if((LASTCH== 'e' || LASTCH== 'E') &&
(isdigit(CH)||CH== '+'||CH=='-'))goto double2;
/* a normal integer */
REGET();
if( l <= r-0.5) {
/* converting integer to real */
if(WARNFLAG)ws("WARNING: converting integer to real\n");
return mkreal(sign ? -r : r);
}
if(i==l){
/* a normal integer */
return mkint(sign ? -i : i);
}
else {
/* a long integer */
return mklong(sign ? -l : l);
}
double1:
expo=0;
while(isdigit(CH)){
expo--;
r=r * 10.0 + (REAL)(CH - '0');
GETCHAR();
}
r=genreal(r,expo);
GETCHAR();
if((LASTCH== 'e' || LASTCH== 'E')&
(isdigit(CH)||CH== '+'||CH=='-'))goto double2;
REGET();
return mkreal( sign ? -r : r);
double2:
/* scanning the exponent */
/* exponent starts with CH */
switch (CH){
case '-' : esign=true;
case '+' : GETCHAR();
}
expo=0; /* no exponent=> exponent=0 */
while(isdigit(CH)){
if(expo < 1000 )expo=expo * 10 + (CH - '0');
GETCHAR();
}
r=genreal(r, esign ? -expo : expo);
return mkreal(sign ? -r : r);
}
#endif
#if ! REALARITH && LONGARITH
LOCAL TERM readnumber(boolean sign)
{
LONG l ; int i ;
l= (LONG)(i=LASTCH-'0');
while(isdigit(CH))
{
l=l * 10l + (LONG)(CH -'0');
i=i * 10 + (CH -'0');
GETCHAR();
}
if(i==l) return mkint(sign ? -i : i);
else return mklong(sign ? -l : l);
}
#endif
#if ! REALARITH && !LONGARITH
LOCAL TERM readnumber(boolean sign)
{
int i ;
i=LASTCH-'0';
while(isdigit(CH))
{
i=i * 10 + (CH -'0');
GETCHAR();
}
return mkint(sign ? -i : i);
}
#endif
#if REALARITH && !LONGARITH
LOCAL TERM readnumber(boolean sign)
{int i ; REAL r ;
boolean esign=false;
int expo=0;
i=LASTCH-'0';
r= (REAL)i;
while(isdigit(CH)){
i=i * 10 + (CH -'0');
r=r * 10.0 + (REAL)(CH -'0');
GETCHAR();
}
GETCHAR();
if(LASTCH== '.' && isdigit(CH))goto double1;
if((LASTCH== 'e' || LASTCH== 'E') &&
(isdigit(CH)||CH== '+'||CH=='-'))goto double2;
/* a normal integer */
REGET();
if( i <= r-0.5) {
/* converting integer to real */
if(WARNFLAG)ws("WARNING: converting integer to real\n");
return mkreal(sign ? -r : r);
}
/* a normal integer */
return mkint(sign ? -i : i);
double1:
expo=0;
while(isdigit(CH)){
expo--;
r=r * 10.0 + (REAL)(CH - '0');
GETCHAR();
}
r=genreal(r,expo);
GETCHAR();
if((LASTCH== 'e' || LASTCH== 'E') &&
(isdigit(CH)||CH== '+'||CH=='-'))goto double2;
REGET();
return mkreal( sign ? -r : r);
double2:
/* scanning the exponent */
/* exponent starts with CH */
switch (CH){
case '-' : esign=true;
case '+' : GETCHAR();
}
expo=0; /* no exponent=> exponent=0 */
while(isdigit(CH)){
if(expo < 1000 )expo=expo * 10 + (CH - '0');
GETCHAR();
}
r=genreal(r, esign ? -expo : expo);
return mkreal(sign ? -r : r);
}
#endif
TERM READIN (void)
{ TERM T, X;
ATOM A,HA,TA,XA;
int N,TTOP;
STATE K; PREC H;
boolean atom_is_quoted=false;
RTOP=0;
STOP=0;
VARHWM=0;
VARCOUNT=0;
RPUSH(MARKL,nil_atom,nil_term);
CONTEXT=OUTERK;
OPEXPECTED=false;
HIPREC=MAXPREC;
GETCHAR(); /* next char is CH */
for(;;)
{ if(FILEENDED())
{ if(RTOP <=1) return mkatom(END_0);
/* End of file - represented by end. */
goto fullstop;
}
atom_is_quoted=false;
ERRPOS=CHARPOS;
GETCHAR();
switch (CHARCLASS[LASTCH])
{ case SC:
ATOMINDEX=0;
ATOMTAB[ATOMINDEX++]=LASTCH;
while( SC<=CHARCLASS[CH] && CHARCLASS[CH]<=DC )
{ if(ATOMINDEX>=STRINGSPACE) ERROR(aSTRINGSPACEE);
ATOMTAB[ATOMINDEX++]=CH;
GETCHAR();
}
goto new_atom;
case '\'':
SCANQUOTE('\''); atom_is_quoted=true;
goto new_atom;
case '"':
SCANQUOTE('"');
ATOMTAB[ATOMINDEX++]=0;
T=LISTREP(ATOMTAB); TA=name(T); T=son(T); goto shift;
case OC:
if(LASTCH=='/' && CH=='*')
/* A comment. Comments don't nest. */
{
GETCHAR();
do {GETCHAR();if(FILEENDED())ERROR(COMMENTE);}
while(LASTCH!='*' || CH!='/');
GETCHAR();;
continue;
}
if(LASTCH== '%')
/* also a comment */
{ if(CH != '\n')
while(!LINEENDED()) GETCHAR();
GETCHAR();
continue;
}
if(LASTCH=='-' && CHARCLASS[CH]==DC && !OPEXPECTED)
/* A negative number. */
{ GETCHAR();
T=readnumber(true); TA=VART; goto shift; }
if(LASTCH=='.' && CHARCLASS[CH]==C0)
/* A full stop. */
{
fullstop:
#if CPM
if(CH==13) GETCHAR();
#endif
CHECKDELIM();
if(CONTEXT!=OUTERK) SYNERROR(BADDOTE);
if(WARNFLAG && !In_Toplevel_Read)Var_Check();
RPOP(&TA,&T); return mkfunc(TA,T);
}
ATOMINDEX=0;
ATOMTAB[ATOMINDEX++]=LASTCH;
while(CHARCLASS[CH]==OC)
{ if(ATOMINDEX>=STRINGSPACE) ERROR(aSTRINGSPACEE);
ATOMTAB[ATOMINDEX++]=CH;
GETCHAR();
}
goto new_atom;
case BC:
/* An anonymous able: replaced by a unique ordinary able. */
if(LASTCH=='_' && (CHARCLASS[CH]>DC || CHARCLASS[CH]==0))
{ TA=UNBOUNDT; T=nil_term; goto shift; }
/* ordinary variables */
T=ENTERVAR(); TA=VART; goto shift;
case DC:
/* positiv numbers */
T=readnumber(false); TA=VART; goto shift;
case '(':
K=INNERK; H=MAXPREC; goto enter;
case ')':
CHECKDELIM();
switch (CONTEXT)
{ case INNERK:
RPOP(&TA,&T); goto exit;
case FUNCK:
/* assemble a function call */
TTOP=RTOP--;
for(N=1; TAGSTACK[RTOP]==TERML; RTOP--) N++;
RTOP=TTOP;
X=stackterms(N); TTOP=N;
while(N-->0)
{ TERM ARGS; ATOM ARGA;
RPOP(&ARGA,&ARGS);
name(X+term_units(N))=ARGA; son(X+term_units(N))=ARGS;
}
T=X; TA=LOOKATOM(ASTACK[RTOP],TTOP);
goto exit;
default:
SYNERROR(BADKETE);
}
case '!':
A=CUT_0;goto get_atom;
case '~':
#if SYMBOLARITH
A=TILDE_0;goto get_atom;
#endif
#if !SYMBOLARITH
ATOMINDEX=0;
ATOMTAB[ATOMINDEX++]='~';
goto new_atom;
#endif
case '[':
while(CHARCLASS[CH]==C0 && !FILEENDED())GETCHAR();
if(CH==']') /* The empty list []. */
{ GETCHAR(); A=NIL_0; goto get_atom; }
K=LISTK; H=SUBPREC; goto enter;
case ']':
CHECKDELIM();
if(CONTEXT==LISTK)
RPUSH(TERML,NIL_0,nil_term);
else if(CONTEXT!=ENDLISTK)
SYNERROR(BADKETE);
/* assemble a list */
RPOP( &TA, &T);
do { RPOP( &XA, &X); T=mk2sons(XA,X,TA,T); TA=CONS_2; }
while(TAGSTACK[RTOP]==TERML);
goto exit;
case '{':
while(CHARCLASS[CH]==C0 && !FILEENDED())GETCHAR();
if(CH==RBRACE) /* The 'curly' atom. */
{ GETCHAR(); A=CURLY_0; goto get_atom; }
K=CURLYK; H=MAXPREC; goto enter;
case '}':
CHECKDELIM();
if(CONTEXT!=CURLYK) SYNERROR(BADKETE);
RPOP(&TA,&T); T=mkfunc(TA,T); TA=CURLY_1; goto exit;
case ',':
switch(CONTEXT)
{ case OUTERK: case INNERK: case CURLYK:
A=COMMA_2; goto get_atom;
case FUNCK: case LISTK:
CHECKDELIM();
OPEXPECTED=false;
HIPREC=SUBPREC;
continue;
default:
SYNERROR(BADCDDE);
}
case '|':
CHECKDELIM();
if(CONTEXT!=LISTK) SYNERROR(BADCDDE);
CONTEXT=ENDLISTK;
OPEXPECTED=false;
HIPREC=SUBPREC;
continue;
case C0:
continue;
default:
SYNERROR(WIERDCHE);
}
/* semantic actions */
new_atom:
ATOMTAB[ATOMINDEX++]=0;
A=LOOKUP(ATOMTAB,0,false);
get_atom:
if(!OPEXPECTED)
{
if(CH=='(') /* functor in standard notation. */
{ GETCHAR(); RPUSH(FUNCL,A,nil_term);
K=FUNCK; H=SUBPREC;
goto enterfunc;
}
if(atom_is_quoted) goto quot_atom;
HA=LOOKATOM(A,-1);
if(oclass(HA)==FXO || oclass(HA)==FYO)
{ A=HA;
if(oprec(A)>HIPREC) SYNERROR(PRECE);
RPUSH(OPL,A,nil_term);
OPEXPECTED=false; HIPREC=RPREC(A);
continue;
}
/* An atom, i.e. a functor of tarity 0. */
quot_atom:
A=LOOKATOM(A,0);
RPUSH(TERML,A,nil_term);
OPEXPECTED=true; LOPREC=0;
continue;
}
/* OPEXPECTED ! */
if(atom_is_quoted) SYNERROR(NEEDOPE);
HA=LOOKATOM(A,-1);
if(oclass(HA)==XFO || oclass(HA)==YFO)
{ TERM Y; ATOM YA;
A=HA;
SQUASHRAND(A);
RPOP(&YA,&Y);
Y=mkfunc(YA,Y);
RPUSH(TERML,A,Y);
OPEXPECTED=true; LOPREC=oprec(A);
continue;
}
HA=LOOKATOM(A,-2);
if(oclass(HA)==XFXO || oclass(HA)==XFYO || oclass(HA)==YFXO)
{ A=HA;
SQUASHRAND(A);
RPUSH(OPL,A,nil_term);
OPEXPECTED=false; HIPREC=RPREC(A);
continue;
}
else
SYNERROR(NEEDOPE);
shift:
if(OPEXPECTED) SYNERROR(NEEDOPE);
RPUSH(TERML,TA,T);
OPEXPECTED=true;
LOPREC=0;
continue;
enter:
if(OPEXPECTED) SYNERROR(NEEDOPE);
RPUSH(MARKL,nil_atom,nil_term);
enterfunc: /* also called for call in standard syntax */
SAVECONTEXT();
CONTEXT=K;
OPEXPECTED=false;
HIPREC=H;
continue;
exit:
RTOP--; RPUSH(TERML,TA,T);
RESTORECONTEXT();
OPEXPECTED=true;
LOPREC=0;
continue;
}
/* ReadIn */
}
GLOBAL boolean DOREAD(void)
/* read/2 */
{
TERM T,TT,Q;
int i;
if(!UNI(A0,READIN())) return false;
TT=T=mkatom(CONS_2);
for(i=0; i < VARCOUNT ; ++i)
{
Q=mk2sons(LOOKUP(aIDENT[i],0,false),nil_term,VART,VAR_TAB[i]);
son(T)=mk2sons(ISEQ_2,Q,CONS_2,nil_term);
T=br(son(T));
}
name(T)=NIL_0;
son(T)=nil_term;
return UNI(TT,A1);
}